/*
 *
 *  Copyright (C) 2009 GSyC/LibreSoft
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Author : Roberto Calvo Palomino <rocapal@gsyc.es>
 *
 */


package com.LibreGeoSocial.App.Routes;


import java.util.ArrayList;

import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;

import com.LibreGeoSocial.Api.LibreGeoSocial;
import com.LibreGeoSocial.App.GeoNames.AltitudeManager;

public class LocationService extends Service {
	
	
	private static IRouteServiceListener ROUTE_UPDATE_LISTENER;
	
	private static ArrayList <ILocationServiceListener> arrayLocationListener = 
												new ArrayList<ILocationServiceListener>();
	
	private static String TraceName;
	
	private static String LocProvider;
	
	private static Location currentLocation = null;
	
	public static Location lastKnownLocation = null;
	
	private NotificationManager mNM;
	
	private static LocationManager mLocationManager;
	private RoutePositionListener mLocationListener = null;
	
	// Location Unit (seconds:1 or minutes:60), by default: seconds.
	static Integer LocationUnit = null;
	
	// Location Periodic in seconds, by default 2 minutes.
	static Integer LocationPeriodic = null; 
	
	// Minimum distance of gps refresh
	static Integer MinimumDistance = null;
	
	// manager for routes
	private RouteManager routeManager;
	
	// 
	private static ArrayList<Location> points = new ArrayList<Location>();
	
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
   @Override
    public void onCreate() {
       
	   startService();
	   
    }

   @Override
   public void onDestroy() {

       if (mLocationListener != null)
    	   mLocationManager.removeUpdates(mLocationListener);


 
   }
   
   public static void initRoute()
   {
	   points.clear();
   }
   
   public static void setProvider (String provider)
   {
	   LocProvider = provider;   
   }
   
   public static void setRouteUpdateListener (IRouteServiceListener l) 
   {
	   ROUTE_UPDATE_LISTENER = l;	
	   
	   if (ROUTE_UPDATE_LISTENER != null)
		   initRoute();
   }
   
   public static Integer registerLocationListener (ILocationServiceListener l)
   {
	 
	   arrayLocationListener.add(l);
	  
	   return arrayLocationListener.size();
   }
   
   public static void  unRegisterLocationListener (Integer pos)
   {
	   arrayLocationListener.remove(pos-1);
   }
   
   public static void setTraceName (String name) 
   {
	   TraceName = name;	   
   }
   
   public static Location getCurrentLocation ()
   {	   
	   if (currentLocation == null)
		   return lastKnownLocation;
	   
	   return currentLocation;
   }
   
   //FIXME Change the following method when this service knew user id
   public static void setLastKnownLocation (Location lastKnownLocation)
   {	   
	   LocationService.lastKnownLocation = lastKnownLocation;
   }
   
   public static Location getLastKnowLocation ()
   {
	   return mLocationManager.getLastKnownLocation(LocProvider);
   }

   /**
    *  This setter method is necessary for manual location cases 
    */
   public static void setCurrentLocation (Location currentLocation){
	   LocationService.currentLocation = currentLocation;
   }
   

    private void startService() {
    	
    	mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    	
		mLocationListener = new RoutePositionListener();
		
    	loadConfig();
    	
    	Log.e("LGS-Service:",LocProvider);
		
		mLocationManager.requestLocationUpdates( LocProvider, 
												 ((LocationPeriodic)* 1000) * LocationUnit, 
												 MinimumDistance, 
												 mLocationListener);
		
		

		
    }
    
    
    private class RoutePositionListener implements LocationListener 
    {

        public void onLocationChanged(Location loc) {

        	if (loc != null) {


    			//request for altitude info before when provider is not GPS
    			if(LocProvider.equals(LocationManager.NETWORK_PROVIDER))
    				loc.setAltitude(AltitudeManager.getAltitudeFromLatLong(
    						(float)loc.getLatitude(), (float)loc.getLongitude()));
    			
    			// Save the current location
				currentLocation = loc;				
        		
        		
        		if (ROUTE_UPDATE_LISTENER != null) {

        			if (routeManager == null)
        			{
        				routeManager = new RouteManager(getBaseContext());
        	    	
        				routeManager.setStorageSDCard(false);
        				routeManager.setTraceName(TraceName);
        			}
        			
            		routeManager.saveTrace(loc);
            		points.add(loc);
            		
        			ROUTE_UPDATE_LISTENER.updateRoutePoints(points);
        			
        		}
 
        		if (arrayLocationListener.size() > 0)
        		{
        			// Update location in server
        			
        			
        			LibreGeoSocial.getInstance().setUserPosition (loc.getLatitude(), 
        														  loc.getLongitude(),
        														  loc.getAltitude());
 
        			
        			// Execute all the listener
        			for (int i=0; i<arrayLocationListener.size(); i++)
        				arrayLocationListener.get(i).updateCurrentLocation(loc);        						        			
        			
        		}
            }
            

        }


        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub
        }


        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub
        }


        public void onStatusChanged(String provider, int status, 
            Bundle extras) {
            // TODO Auto-generated method stub
        }
    }
    
    public static String getLocProvider()
    {
    	return LocProvider;
    }
    
    private void loadConfig ()
	{
		
		SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
		
		Editor editor = sharedPreferences.edit();
		
		String s_provider = sharedPreferences.getString(RoutePreferences.KEY_LOCATION_PROVIDERS, null);
			
		if (s_provider == null)
		{
			LocProvider = LocationManager.NETWORK_PROVIDER;
			editor.putString (RoutePreferences.KEY_LOCATION_PROVIDERS, LocProvider);
		}
		else
		{
			
			if (s_provider.equals("gps"))
				LocProvider = LocationManager.GPS_PROVIDER;
			
			else		
				LocProvider = LocationManager.NETWORK_PROVIDER;
			
		}
		// Time unit
		String s_unit = sharedPreferences.getString(RoutePreferences.KEY_LOCATION_UNITS, null);
		
		if (s_unit == null)
		{
			LocationUnit = 60;
			editor.putString(RoutePreferences.KEY_LOCATION_UNITS, "60");
		}
		else
		{			
			Integer unit = Integer.valueOf(s_unit);
				
			LocationUnit = unit;
		}

		// Time periodic
		String s_periodic = sharedPreferences.getString(RoutePreferences.KEY_LOCATION_PERIODIC, null);
		
		if (s_periodic==null)
		{
			LocationPeriodic = 2;
			editor.putString(RoutePreferences.KEY_LOCATION_PERIODIC, "2");
			
		}
		else
		{
			Integer periodic = Integer.valueOf(s_periodic);
			LocationPeriodic = periodic;
		}

		//Minimum Distance
		String s_minDistance = sharedPreferences.getString(RoutePreferences.KEY_LOCATION_DISTANCE, null);
		if (s_minDistance == null)
		{
			MinimumDistance = 10;
			editor.putString(RoutePreferences.KEY_LOCATION_DISTANCE, "20");
		
		}
		else
		{			
			Integer minDistance = Integer.valueOf(s_unit);				
			MinimumDistance = minDistance;
		}	

		editor.commit();
		
	}

}
